home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_147 / src / file.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  12KB  |  473 lines

  1. /*
  2.  *        File commands.
  3.  */
  4. #include    "def.h"
  5.  
  6. BUFFER    *findbuffer();
  7. VOID    makename();
  8. VOID    upmodes();
  9. static    char *itos();
  10.  
  11. /*
  12.  * insert a file into the current buffer. Real easy - just call the
  13.  * insertfile routine with the file name.
  14.  */
  15. /*ARGSUSED*/
  16. fileinsert(f, n)
  17. {
  18.     register int    s;
  19.     char        fname[NFILEN];
  20.  
  21.     if ((s=ereply("Insert file: ", fname, NFILEN)) != TRUE)
  22.         return (s);
  23.     return insertfile(adjustname(fname), (char *) NULL);
  24.                         /* don't set buffer name */
  25. }
  26.  
  27. /*
  28.  * Select a file for editing.
  29.  * Look around to see if you can find the
  30.  * fine in another buffer; if you can find it
  31.  * just switch to the buffer. If you cannot find
  32.  * the file, create a new buffer, read in the
  33.  * text, and switch to the new buffer.
  34.  */
  35. /*ARGSUSED*/
  36. filevisit(f, n)
  37. {
  38.     register BUFFER *bp;
  39.     int    s;
  40.     char    fname[NFILEN];
  41.     char    *adjf;
  42.  
  43.     if ((s=ereply("Find file: ", fname, NFILEN)) != TRUE)
  44.         return s;
  45.     adjf = adjustname(fname);
  46.     if ((bp = findbuffer(adjf)) == NULL) return FALSE;
  47.     curbp = bp;
  48.     if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
  49.     if (bp->b_fname[0] == 0)
  50.         return readin(adjf);        /* Read it in.        */
  51.     return TRUE;
  52. }
  53.  
  54. /*
  55.  * Pop to a file in the other window. Same as last function, just
  56.  * popbuf instead of showbuffer.
  57.  */
  58. /*ARGSUSED*/
  59. poptofile(f, n)
  60. {
  61.     register BUFFER *bp;
  62.     register WINDOW *wp;
  63.     int    s;
  64.     char    fname[NFILEN];
  65.     char    *adjf;
  66.  
  67.     if ((s=ereply("Find file in other window: ", fname, NFILEN)) != TRUE)
  68.         return s;
  69.     adjf = adjustname(fname);
  70.     if ((bp = findbuffer(adjf)) == NULL) return FALSE;
  71.     if ((wp = popbuf(bp)) == NULL) return FALSE;
  72.     curbp = bp;
  73.     curwp = wp;
  74.     if (bp->b_fname[0] == 0)
  75.         return readin(adjf);        /* Read it in.        */
  76.     return TRUE;
  77. }
  78.  
  79. /*
  80.  * given a file name, either find the buffer it uses, or create a new
  81.  * empty buffer to put it in.
  82.  */
  83. BUFFER *
  84. findbuffer(fname)
  85. char *fname;
  86. {
  87.     register BUFFER *bp;
  88.     char    bname[NBUFN], *cp;
  89.     unsigned count = 1;
  90.  
  91.     for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
  92.         if (fncmp(bp->b_fname, fname) == 0)
  93.             return bp;
  94.     }
  95.     makename(bname, fname);            /* New buffer name.    */
  96.     cp = bname + strlen(bname);
  97.     while(bfind(bname, FALSE) != NULL) {
  98.         *cp = '<';        /* add "<count>" to then name    */
  99.         (VOID) strcpy(itos(cp, ++count)+1, ">");
  100.     }
  101.     return bfind(bname, TRUE);
  102. }
  103.  
  104. /*
  105.  * Put the decimal representation of num into a buffer.  Hacked to be
  106.  * faster, smaller, and less general.
  107.  */
  108. static char *itos(bufp, num)
  109. char *bufp;
  110. unsigned num;
  111. {
  112.     if (num >= 10) {
  113.         bufp = itos(bufp, num/10);
  114.         num %= 10;
  115.     }
  116.     *++bufp = '0' + num;
  117.     return bufp;
  118. }
  119.  
  120. /*
  121.  * Read the file "fname" into the current buffer.
  122.  * Make all of the text in the buffer go away, after checking
  123.  * for unsaved changes. This is called by the "read" command, the
  124.  * "visit" command, and the mainline (for "uemacs file").
  125.  */
  126. readin(fname) char *fname; {
  127.     register int        status;
  128.     register WINDOW        *wp;
  129.  
  130.     if (bclear(curbp) != TRUE)        /* Might be old.    */
  131.         return TRUE;
  132.     status = insertfile(fname, fname) ;
  133.     curbp->b_flag &= ~BFCHG;        /* No change.        */
  134.     for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  135.         if (wp->w_bufp == curbp) {
  136.             wp->w_dotp  = wp->w_linep = lforw(curbp->b_linep);
  137.             wp->w_doto  = 0;
  138.             wp->w_markp = NULL;
  139.             wp->w_marko = 0;
  140.         }
  141.     }
  142.     return status;
  143. }
  144. /*
  145.  * insert a file in the current buffer, after dot. Set mark
  146.  * at the end of the text inserted, point at the beginning.
  147.  * Return a standard status. Print a summary (lines read,
  148.  * error message) out as well. If the
  149.  * BACKUP conditional is set, then this routine also does the read
  150.  * end of backup processing. The BFBAK flag, if set in a buffer,
  151.  * says that a backup should be taken. It is set when a file is
  152.  * read in, but not on a new file (you don't need to make a backup
  153.  * copy of nothing).
  154.  */
  155. insertfile(fname, newname) char fname[], newname[]; {
  156.     register LINE    *lp1;
  157.     register LINE    *lp2;
  158.     register WINDOW *wp;
  159.     int        nbytes;
  160.     LINE        *olp;            /* Line we started at */
  161.     int        opos;            /* and offset into it */
  162.     int        s, nline;
  163.     BUFFER        *bp;
  164.     char        line[NLINE];
  165.  
  166.     bp = curbp;                /* Cheap.        */
  167.     if (newname != (char *) NULL)
  168.         (VOID) strcpy(bp->b_fname, newname);
  169.     if ((s=ffropen(fname)) == FIOERR)    /* Hard file open.    */
  170.         goto out;
  171.     if (s == FIOFNF) {            /* File not found.    */
  172.         if (newname != NULL)
  173.             ewprintf("(New file)");
  174.         else    ewprintf("(File not found)");
  175.         goto out;
  176.     }
  177.     opos = curwp->w_doto;
  178.     /* Open a new line, at point, and start inserting after it */
  179.     (VOID) lnewline();
  180.     olp = lback(curwp->w_dotp);
  181.     if(olp == curbp->b_linep) {
  182.         /* if at end of buffer, create a line to insert before */
  183.         (VOID) lnewline();
  184.         curwp->w_dotp = lback(curwp->w_dotp);
  185.     }
  186.     nline = 0;            /* Don't count fake line at end */
  187.     while ((s=ffgetline(line, NLINE, &nbytes)) != FIOERR) {
  188.         switch(s) {
  189.         case FIOSUC:
  190.         ++nline;
  191.         /* and continue */
  192.         case FIOEOF:    /* the last line of the file        */
  193.         if ((lp1=lalloc(nbytes)) == NULL) {
  194.             s = FIOERR;        /* Keep message on the    */
  195.             goto endoffile;        /* display.        */
  196.         }
  197.         bcopy(line, <ext(lp1)[0], nbytes);
  198. lineread:    lp2 = lback(curwp->w_dotp);
  199.         lp2->l_fp = lp1;
  200.         lp1->l_fp = curwp->w_dotp;
  201.         lp1->l_bp = lp2;
  202.         curwp->w_dotp->l_bp = lp1;
  203.         if(s==FIOEOF) goto endoffile;
  204.         break;
  205.         case FIOLONG: {    /* a line to long to fit in our buffer    */
  206.             char *cp;
  207.             char *cp2;
  208.             int     i;
  209.  
  210.             nbytes = 0;
  211.             for(;;) {
  212.             if((cp = malloc((unsigned)(nbytes + NLINE))) == NULL) {
  213.                 ewprintf("Could not allocate %d bytes",
  214.                     nbytes + NLINE);
  215.                 s = FIOERR;
  216.                 if(nbytes) free(cp2);
  217.                 goto endoffile;
  218.             }
  219.             if(nbytes) {
  220.                 bcopy(cp2, cp, nbytes);
  221.                 free(cp2);
  222.             }
  223.             bcopy(line, cp+nbytes, NLINE);
  224.             nbytes += NLINE;
  225.             switch(s = ffgetline(line, NLINE, &i)) {
  226.                 case FIOERR:
  227.                 free(cp);
  228.                 goto endoffile;
  229.                 case FIOLONG:
  230.                 cp2 = cp;
  231.                 break;
  232.                 case FIOEOF:
  233.                 case FIOSUC:
  234.                 if((lp1=lalloc(nbytes+i)) == NULL) {
  235.                     s = FIOERR;
  236.                     free(cp);
  237.                     goto endoffile;
  238.                 }
  239.                 bcopy(cp, <ext(lp1)[0], nbytes);
  240.                 bcopy(line, <ext(lp1)[nbytes], i);
  241.                 goto lineread;
  242.             }
  243.             }
  244.         }
  245.         default:
  246.         ewprintf("Unknown code %d reading file", s);
  247.         s = FIOERR;
  248.         break;
  249.         }
  250.     }
  251. endoffile:
  252.     (VOID) ffclose();            /* Ignore errors.    */
  253.     if (s==FIOEOF) {            /* Don't zap an error.    */
  254.         if (nline == 1) ewprintf("(Read 1 line)");
  255.         else        ewprintf("(Read %d lines)", nline);
  256.     }
  257.     /* Set mark at the end of the text */
  258.     curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp);
  259.     curwp->w_marko = llength(curwp->w_markp);
  260.     (VOID) ldelnewline();
  261.     curwp->w_dotp = olp;
  262.     curwp->w_doto = opos;
  263.     if(olp == curbp->b_linep) curwp->w_dotp = lforw(olp);
  264. #ifndef NO_BACKUP
  265.     if (newname != NULL)
  266.         bp->b_flag |= BFCHG | BFBAK;    /* Need a backup.    */
  267.     else    bp->b_flag |= BFCHG;
  268. #else
  269.     bp->b_flag |= BFCHG;
  270. #endif
  271.     /* if the insert was at the end of buffer, set lp1 to the end of
  272.      * buffer line, and lp2 to the beginning of the newly inserted
  273.      * text.  (Otherwise lp2 is set to NULL.)  This is
  274.      * used below to set pointers in other windows correctly if they
  275.      * are also at the end of buffer.
  276.      */
  277.     lp1 = bp->b_linep;
  278.     if (curwp->w_markp == lp1) {
  279.         lp2 = curwp->w_dotp;
  280.     } else {
  281.         (VOID) ldelnewline();        /* delete extranious newline */
  282. out:        lp2 = NULL;
  283.     }
  284.     for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  285.         if (wp->w_bufp == curbp) {
  286.             wp->w_flag |= WFMODE|WFEDIT;
  287.             if (wp != curwp && lp2 != NULL) {
  288.                 if (wp->w_dotp == lp1)    wp->w_dotp  = lp2;
  289.                 if (wp->w_markp == lp1) wp->w_markp = lp2;
  290.                 if (wp->w_linep == lp1) wp->w_linep = lp2;
  291.             }
  292.         }
  293.     }
  294.     return s != FIOERR;            /* False if error.    */
  295. }
  296.  
  297. /*
  298.  * Take a file name, and from it
  299.  * fabricate a buffer name. This routine knows
  300.  * about the syntax of file names on the target system.
  301.  * BDC1        left scan delimiter.
  302.  * BDC2        optional second left scan delimiter.
  303.  * BDC3        optional right scan delimiter.
  304.  */
  305. VOID
  306. makename(bname, fname) char bname[]; char fname[]; {
  307.     register char    *cp1;
  308.     register char    *cp2;
  309.  
  310.     cp1 = &fname[0];
  311.     while (*cp1 != 0)
  312.         ++cp1;
  313.     --cp1;            /* insure at least 1 character ! */
  314. #ifdef    BDC2
  315.     while (cp1!=&fname[0] && cp1[-1]!=BDC1 && cp1[-1]!=BDC2)
  316.         --cp1;
  317. #else
  318.     while (cp1!=&fname[0] && cp1[-1]!=BDC1)
  319.         --cp1;
  320. #endif
  321.     cp2 = &bname[0];
  322. #ifdef    BDC3
  323.     while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=BDC3)
  324.         *cp2++ = *cp1++;
  325. #else
  326.     while (cp2!=&bname[NBUFN-1] && *cp1!=0)
  327.         *cp2++ = *cp1++;
  328. #endif
  329.     *cp2 = 0;
  330. }
  331.  
  332. /*
  333.  * Ask for a file name, and write the
  334.  * contents of the current buffer to that file.
  335.  * Update the remembered file name and clear the
  336.  * buffer changed flag. This handling of file names
  337.  * is different from the earlier versions, and
  338.  * is more compatable with Gosling EMACS than
  339.  * with ITS EMACS.
  340.  */
  341. /*ARGSUSED*/
  342. filewrite(f, n)
  343. {
  344.     register int    s;
  345.     char        fname[NFILEN];
  346.     char        *adjfname;
  347.  
  348.     if ((s=ereply("Write file: ", fname, NFILEN)) != TRUE)
  349.         return (s);
  350.     adjfname = adjustname(fname);
  351.     if ((s=writeout(curbp, adjfname)) == TRUE) {
  352.         (VOID) strcpy(curbp->b_fname, adjfname);
  353. #ifndef NO_BACKUP
  354.         curbp->b_flag &= ~(BFBAK | BFCHG);
  355. #else
  356.         curbp->b_flag &= ~BFCHG;
  357. #endif
  358.         upmodes(curbp);
  359.     }
  360.     return s;
  361. }
  362.  
  363. /*
  364.  * Save the contents of the current buffer back into
  365.  * its associated file.
  366.  */
  367. #ifndef NO_BACKUP
  368. #ifndef    MAKEBACKUP
  369. #define    MAKEBACKUP TRUE
  370. #endif
  371. static int    makebackup = MAKEBACKUP;
  372. #endif
  373.  
  374. /*ARGSUSED*/
  375. filesave(f, n)
  376. {
  377.     return buffsave(curbp);
  378. }
  379.  
  380. /*
  381.  * Save the contents of the buffer argument into its associated file.
  382.  * Do nothing if there have been no changes
  383.  * (is this a bug, or a feature). Error if there is no remembered
  384.  * file name. If this is the first write since the read or visit,
  385.  * then a backup copy of the file is made.
  386.  * Allow user to select whether or not to make backup files
  387.  * by looking at the value of makebackup.
  388.  */
  389. buffsave(bp) BUFFER *bp; {
  390.     register int    s;
  391.  
  392.     if ((bp->b_flag&BFCHG) == 0)    {    /* Return, no changes.    */
  393.         ewprintf("(No changes need to be saved)");
  394.         return TRUE;
  395.     }
  396.     if (bp->b_fname[0] == '\0') {        /* Must have a name.    */
  397.         ewprintf("No file name");
  398.         return (FALSE);
  399.     }
  400. #ifndef NO_BACKUP
  401.     if (makebackup && (bp->b_flag&BFBAK)) {
  402.         s = fbackupfile(bp->b_fname);
  403.         if (s == ABORT)            /* Hard error.        */
  404.             return FALSE;
  405.         if (s == FALSE            /* Softer error.    */
  406.         && (s=eyesno("Backup error, save anyway")) != TRUE)
  407.             return s;
  408.     }
  409. #endif
  410.     if ((s=writeout(bp, bp->b_fname)) == TRUE) {
  411. #ifndef NO_BACKUP
  412.         bp->b_flag &= ~(BFCHG | BFBAK);
  413. #else
  414.         bp->b_flag &= ~BFCHG;
  415. #endif
  416.         upmodes(bp);
  417.     }
  418.     return s;
  419. }
  420.  
  421. #ifndef NO_BACKUP
  422. /* Since we don't have variables (we probably should)
  423.  * this is a command processor for changing the value of
  424.  * the make backup flag.  If no argument is given,
  425.  * sets makebackup to true, so backups are made.  If
  426.  * an argument is given, no backup files are made when
  427.  * saving a new version of a file. Only used when BACKUP
  428.  * is #defined.
  429.  */
  430. /*ARGSUSED*/
  431. makebkfile(f, n)
  432. {
  433.     if(f & FFARG) makebackup = n > 0;
  434.     else makebackup = !makebackup;
  435.     ewprintf("Backup files %sabled", makebackup ? "en" : "dis");
  436.     return TRUE;
  437. }
  438. #endif
  439.  
  440. /*
  441.  * This function performs the details of file
  442.  * writing; writing the file in buffer bp to
  443.  * file fn. Uses the file management routines
  444.  * in the "fileio.c" package. Most of the grief
  445.  * is checking of some sort.
  446.  */
  447. writeout(bp, fn) register BUFFER *bp; char *fn; {
  448.     register int    s;
  449.  
  450.     if ((s=ffwopen(fn)) != FIOSUC)        /* Open writes message. */
  451.         return (FALSE);
  452.     s = ffputbuf(bp);
  453.     if (s == FIOSUC) {            /* No write error.    */
  454.         s = ffclose();
  455.         if (s==FIOSUC)
  456.             ewprintf("Wrote %s", fn);
  457.     } else                    /* Ignore close error    */
  458.         (VOID) ffclose();        /* if a write error.    */
  459.     return s == FIOSUC;
  460. }
  461.  
  462. /*
  463.  * Tag all windows for bp (all windows if bp NULL) as needing their
  464.  * mode line updated.
  465.  */
  466. VOID
  467. upmodes(bp) register BUFFER *bp; {
  468.     register WINDOW *wp;
  469.  
  470.     for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  471.         if (bp == NULL || curwp->w_bufp == bp) wp->w_flag |= WFMODE;
  472. }
  473.